<?php
/**
 * Created by PhpStorm.
 * User: Len
 * Date: 2019/1/7
 * Time: 17:42
 * Desc: 爬虫 抓取交易所数据 测试 Demo
 */

namespace Command;


use Helper\Common;
use Library\Logger;
use Swlib\SaberGM;

class SpiderMan
{
    // Bitz
    const BITZ = 'bitz';

    // 币安
    const BINANCE = 'binance';

    // 火币
    const HUOBI = 'huobi';

    // OK
    const OKEX = 'okex';

    // cmc 抓取交易所列表
    const CMC_EXCHANG_LIST = [
        self::BITZ    => 'bit-z',
        self::OKEX    => self::OKEX,
        self::HUOBI   => self::HUOBI,
        self::BINANCE => self::BINANCE,
    ];

    // 排名前100交易所
    const URL_TOP_100 = 'https://coinmarketcap.com/zh/rankings/exchanges/';

    // 获取全部币种排名接口
    const URL_COIN_ALL = 'https://coinmarketcap.com/zh/%s';

    // 单交易对信息
    const URL_ONE_EXCHANGE = 'https://coinmarketcap.com/zh/exchanges/%s/';

    // 美金 对 人民币  汇率
    const URL_CNY_USD_RATE = 'https://apiv2.bitz.com/Market/currencyRate?symbols=cny_usd';

    /**
     * @desc 抓取 100家交易所数据
     * ------------------------------------------------------------
     */
    public function matchTop100Exchange()
    {
        // td 标签映射 字段
        $td_map_list = [
            'rank',
            'exchange',
            'total_volume_24',
            'real_volume_24',
            'total_volume_7',
            'total_volume_30',
            'marker_numer',
            'change_rate',
        ];

        // 需要精度处理的字段
        $double_list = [
            'total_volume_24',
            'real_volume_24',
            'total_volume_7',
            'total_volume_30'
        ];

        go(function () use ($td_map_list, $double_list) {

            [$html, $json] = SaberGM::list([
                'uri' => [
                    self::URL_TOP_100,
                    self::URL_CNY_USD_RATE,
                ],
                //  'proxy' => [] // IP 代理
            ]);

            // 格式化汇率
            $rate_data = $json->getParsedJsonArray() ?? [];

            $rate_cny = $rate_data['data']['cny_usd']['rate'] ?? '0.145915'; // 默认汇率

            // Dome 抓取 html内元素
            $tr_list = $html->getParsedDomObject()
                ->getElementById('exchange-rankings')
                ->getElementsByTagName('tbody')
                ->item(0)
                ->getElementsByTagName('tr');

            // 遍历提取标签中元素
            $exchange_list = $rank_exchange_list = [];
            foreach ($tr_list as $tr_dome) {
                /** @var \DOMElement $tr_dome */
                $td_list = $tr_dome->getElementsByTagName('td');

                $exchange_info = [];
                foreach ($td_list as $key => $item) {
                    if (isset($td_map_list[$key])) {
                        $feild = $td_map_list[$key];
                        $exchange_info[$feild] = trim(trim($item->textContent), '$');

                        // 精度处理方法
                        if (in_array($feild, $double_list)) {
                            $exchange_info[$feild] = str_replace(',', '', $exchange_info[$feild]);
                            $exchange_info[$feild . '_cny'] = Common::sbcdiv($exchange_info[$feild], $rate_cny, 0);
                        }
                    }
                }

                $rank_exchange_list[$exchange_info['rank']] = json_encode($exchange_info);
                $exchange = strtolower($exchange_info['exchange']);
                $exchange_list[$exchange] = json_encode($exchange_info);
            }

            print_r($exchange_list);

            Logger::spiderMan('matchTop100Exchange end');
        });
    }

    /**
     * @desc 捕捉cmc单交易所数据
     * @return void
     * ------------------------------------------------------------
     */
    public function matchCmcOneExchange()
    {
        // td 标签映射 字段
        $td_map_list = [
            'rank',
            'coin',
            'symbol',
            'total_volume',
            'price',
            'rate'
        ];

        // 需要精度处理的字段
        $double_list = [
            'total_volume',
        ];

        go(function () use ($td_map_list, $double_list) {

            $url_list = SpiderMan::createOneExchangeUrl();
            array_unshift($url_list, self::URL_CNY_USD_RATE); // 头部添加汇率


            // 批量请求
            $html_list = SaberGM::list([
                'uri' => $url_list,
                // 'proxy' => [] 代理IP
            ]);

            $json = current($html_list)->getParsedJsonArray() ?? [];
            $rate_cny = $rate_data['data']['cny_usd']['rate'] ?? '0.145915'; // 默认汇率

            // 目标交易所
            $exchange_map_list = array_keys(self::CMC_EXCHANG_LIST);

            foreach ($html_list as $key => $html) {

                // 丢弃第1个数组元素
                if (!$key) continue;
                $key--;

                // 通过 url 映射 获取交易所名称
                $exchange = $exchange_map_list[$key];

                // match 表格下数据
                $tr_list = $html->getParsedDomObject()
                    ->getElementById('exchange-markets');
                if (empty($tr_list)) {
                    echo "获取dom为空";
                    return;
                }
                $tr_list = $tr_list->getElementsByTagName('tbody')
                    ->item(0)
                    ->getElementsByTagName('tr');

                // 遍历 tr 标签 元素
                $exchange_list = $rank_exchange_list = [];
                foreach ($tr_list as $tr_dome) {

                    // 遍历 td 标签 元素
                    /** @var \DOMElement $tr_dome */
                    $td_list = $tr_dome->getElementsByTagName('td');

                    $exchange_info = [];
                    foreach ($td_list as $key => $item) {
                        if (isset($td_map_list[$key])) {
                            $feild = $td_map_list[$key];
                            $exchange_info[$feild] = trim(trim($item->textContent), '$');
                            if (in_array($feild, $double_list)) {
                                $exchange_info[$feild] = str_replace(',', '', $exchange_info[$feild]);
                                $exchange_info[$feild . '_cny'] = Common::sbcdiv($exchange_info[$feild], $rate_cny, 0);

                            } elseif ($feild == 'symbol') {
                                $exchange_info[$feild] = strtolower(str_replace('/', '_', $exchange_info[$feild]));
                            }
                        }
                    }

                    $rank_exchange_list[$exchange_info['rank']] = json_encode($exchange_info);
                    $exchange_list[$exchange_info['symbol']] = json_encode($exchange_info);
                }

            }

            Logger::spiderMan('matchCmcOneExchange end');
        });
    }

    /**
     * @desc 创建交易所列表
     * ------------------------------------------------------------
     */
    private static function createOneExchangeUrl()
    {
        $exchange_list = array_values(self::CMC_EXCHANG_LIST);
        $url_list = [];
        foreach ($exchange_list as $exchange) {
            $url_list[] = sprintf(self::URL_ONE_EXCHANGE, $exchange);
        }

        return $url_list;
    }

    /**
     * @desc  捕捉CMC 交易所 小图并下载更名
     * ------------------------------------------------------------
     */
    public function matchExchangeIco()
    {
        go(function () {

            [$html] = SaberGM::list([
                'uri' => [self::URL_TOP_100],
            ]);

            // Dome 抓取 html内元素
            $tr_list = $html->getParsedDomObject()
                ->getElementById('exchange-rankings')
                ->getElementsByTagName('tbody')
                ->item(0)
                ->getElementsByTagName('tr');

            /** @var \DOMElement $tr_dome */
            foreach ($tr_list as $tr_dome) {

                // 捕获属性
                $logo_img = $tr_dome->getElementsByTagName('td')->item(1)->getElementsByTagName('img')->item(0)->getAttribute('src');
                (!$logo_img || count(explode('http', $logo_img)) < 2) && $logo_img = $tr_dome->getElementsByTagName('td')->item(1)->getElementsByTagName('img')->item(0)->getAttribute('data-src');

                $exchange = trim(strtolower(str_replace([' ', '.', '-'], '', trim($tr_dome->getElementsByTagName('td')->item(1)->textContent))));

                echo $exchange, PHP_EOL;

                // 保存文件
                file_put_contents(BIN_PATH . '../web/logo/exchange/' . $exchange . '.png', file_get_contents($logo_img));
            }
        });
    }

    /**
     * @desc  捕捉CMC 交易所 小图并下载更名
     * ------------------------------------------------------------
     */
    public function matchCoinLogo()
    {
        go(function () {
            $uri_list = [];
            foreach (range(1, 22) as $page) {
                $uri_list[] = sprintf(self::URL_COIN_ALL, $page);
            }
            $html_list = SaberGM::list([
                'uri' => $uri_list,
            ]);

            foreach ($html_list as $html) {

                $tr_list = $html->getParsedDomObject()->getElementById('currencies')->getElementsByTagName('tbody')->item(0)->getElementsByTagName('tr');

                /** @var \DOMElement $tr_dome */
                foreach ($tr_list as $tr_dome) {

                    // 捕获属性
                    $logo_img = trim($tr_dome->getElementsByTagName('td')->item(1)->getElementsByTagName('img')->item(0)->getAttribute('data-src'));

                    $coin = trim(strtolower(preg_replace('/[\,\?\*\. \-|\d]/i', '', trim($tr_dome->getElementsByTagName('td')->item(5)->textContent))));

                    echo $coin, ' logo ', $logo_img, PHP_EOL;
                    if ($logo_img) {
                        $img = file_get_contents($logo_img);
                        // 保存文件
                        file_put_contents(BIN_PATH . '../web/logo/coin/' . $coin . '.png', $img);
                    }
                }
            }

        });

    }
}